package com.member.mp.web;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.member.common.constant.SystemConst;
import com.member.common.core.domain.R;
import com.member.common.utils.DateUtils;
import com.member.common.utils.StringUtils;
import com.member.shop.domain.*;
import com.member.shop.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author wangxin
 * @version 1.0
 * @date 2024/9/27 下午2:55
 **/
@Slf4j
@RestController
@RequestMapping("/wx/payment")
public class PaymentController {
//    @Resource
//    private WxPayService wxService;
    @Resource
    private ISysBizOrderService sysBizOrderService;
    @Resource
    private ISysBizUserSurplusDetailsService sysBizUserSurplusDetailsService;
    @Resource
    private ISysBizRechargeUserService sysBizRechargeUserService;
    @Resource
    private ISysBizUserService sysBizUserService;
    @Resource
    private ISysBizTenantService sysBizTenantService;
    @Resource
    private ISysBizOrderGoodsService sysBizOrderGoodsService;
    @Resource
    private ISysBizGoodsService goodsService;

    @Value("${wx.pay.appId}")
    private String appId;

    @Value("${file.server}")
    private String server;

    /**
     * 订单微信支付回调
     *
     * @param xmlData 微信支付回调参数
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/callbackByOrder")
    public synchronized String callbackByOrder(@RequestBody String xmlData) {
        try {
            log.info("----------- callbackByOrder:{}",xmlData);
            WxPayOrderNotifyResult notifyResultXml = WxPayOrderNotifyResult.fromXML(xmlData);
            String outTradeNoStr = notifyResultXml.getOutTradeNo();

            SysBizOrder bizOrder = sysBizOrderService.getOne(new LambdaQueryWrapper<SysBizOrder>().eq(SysBizOrder::getPaymentId, outTradeNoStr));
            if(bizOrder == null){
                return WxPayNotifyResponse.fail("未查询到订单站点配置信息");
            }

            List<SysBizOrderGoods> list = sysBizOrderGoodsService.list(new LambdaQueryWrapper<SysBizOrderGoods>()
                    .eq(SysBizOrderGoods::getOrderId, bizOrder.getId()));

            List<Long> ids = list.stream().map(SysBizOrderGoods::getGoodsId).distinct().collect(Collectors.toList());

            List<SysBizGoods> goodsList = goodsService.list(new LambdaQueryWrapper<SysBizGoods>().in(SysBizGoods::getId, ids));
            if (!org.springframework.util.CollectionUtils.isEmpty(goodsList)) {
                // 获取下架商品名称列表
                List<String> offShelfNames = goodsList.stream()
                        .filter(g -> g.getGrounding() == 1)
                        .map(SysBizGoods::getName)
                        .collect(Collectors.toList());

                if (!offShelfNames.isEmpty()) {
                    return WxPayNotifyResponse.fail("存在已下架的商品：" + String.join("，", offShelfNames) + "，请重新调整商品");
                }
            }

            SysBizTenant bizTenant = sysBizTenantService.getById(bizOrder.getTenantId());
            if(bizTenant == null){
                return WxPayNotifyResponse.fail("未查询到支付配置信息");
            }

            WxPayConfig payConfig = new WxPayConfig();
            payConfig.setAppId(StringUtils.trimToNull(appId));
            payConfig.setMchId(StringUtils.trimToNull(bizTenant.getWxMchId()));
            payConfig.setMchKey(StringUtils.trimToNull(bizTenant.getWxMchKey()));
//        payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
//        payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
            payConfig.setKeyPath(StringUtils.trimToNull(server+bizTenant.getWxKeyPath()));

            // 可以指定是否使用沙箱环境
            payConfig.setUseSandboxEnv(false);

            WxPayService wxPayService = new WxPayServiceImpl();
            wxPayService.setConfig(payConfig);

            final WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);

            String outTradeNo = notifyResult.getOutTradeNo();
            String transactionId = notifyResult.getTransactionId();
            log.error("订单微信支付回调 callbackByOrder==================>,notifyResult:{},outTradeNo:{},transactionId：{}",notifyResult,outTradeNo,transactionId);

            List<SysBizOrder> sysBizOrders = sysBizOrderService.list(new LambdaQueryWrapper<SysBizOrder>().eq(SysBizOrder::getPaymentId, outTradeNo));
            log.error("订单微信支付回调 callbackByOrder==================>,sysBizOrders size:{}",sysBizOrders.size());
            SysBizOrder sysBizOrder = null;
            if (!CollectionUtils.isEmpty(sysBizOrders)) {
                sysBizOrder = sysBizOrders.get(0);
            }

            if (sysBizOrder == null) {
                log.error("{}:订单为空", outTradeNo);
                return WxPayNotifyResponse.fail("失败");
            }
            if (SystemConst.PAY_SUCCESS.equals(notifyResult.getResultCode())) {
                if (sysBizOrder.getSurplusAmount() != null && sysBizOrder.getSurplusAmount().compareTo(BigDecimal.ZERO) > 0) {
                    sysBizUserSurplusDetailsService.save(SysBizUserSurplusDetails.builder()
                            .userId(sysBizOrder.getUserId())
                            .type(1)
                            .orderId(sysBizOrder.getOrderCode())
                            .createTime(DateUtils.getNowDate())
                            .price(sysBizOrder.getSurplusAmount())
                            .rechargePrice(sysBizOrder.getSurplusAmount())
                            .build());
                }
                sysBizOrder.setPaymentType(0);
                sysBizOrder.setStatus(15);
                sysBizOrder.setPaymentTime(DateUtils.getNowDate());
                sysBizOrder.setPaymentStatus(1);
                sysBizOrder.setPaymentNo(transactionId);
                sysBizOrder.setTransactionId(transactionId);
                sysBizOrderService.updateById(sysBizOrder);
            }
            return WxPayNotifyResponse.success("成功");
        } catch (Exception e) {
            log.error("支付回调异常, error => ", e);
            return WxPayNotifyResponse.fail("失败");
        }
    }




    /**
     * 充值订单微信支付回调
     *
     * @param xmlData 微信支付回调参数
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/callbackBySurplus")
    public synchronized String callbackBySurplus(@RequestBody String xmlData) {
        try {
            log.info("----------- callbackBySurplus:{}",xmlData);

            WxPayOrderNotifyResult notifyResultXml = WxPayOrderNotifyResult.fromXML(xmlData);
            String outTradeNoStr = notifyResultXml.getOutTradeNo();

            SysBizRechargeUser bizRechargeUser = sysBizRechargeUserService.getOne(new LambdaQueryWrapper<SysBizRechargeUser>().eq(SysBizRechargeUser::getPaymentNo, outTradeNoStr));
            if(bizRechargeUser == null){
                return WxPayNotifyResponse.fail("未查询到充值数据");
            }

            SysBizTenant bizTenant = sysBizTenantService.getById(bizRechargeUser.getTenantId());
            if(bizTenant == null){
                return WxPayNotifyResponse.fail("未查询到支付配置信息");
            }

            WxPayConfig payConfig = new WxPayConfig();
            payConfig.setAppId(StringUtils.trimToNull(appId));
            payConfig.setMchId(StringUtils.trimToNull(bizTenant.getWxMchId()));
            payConfig.setMchKey(StringUtils.trimToNull(bizTenant.getWxMchKey()));
//        payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
//        payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
            payConfig.setKeyPath(StringUtils.trimToNull(server+bizTenant.getWxKeyPath()));

            // 可以指定是否使用沙箱环境
            payConfig.setUseSandboxEnv(false);

            WxPayService wxPayService = new WxPayServiceImpl();
            wxPayService.setConfig(payConfig);

            final WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
            log.info("订单微信支付回调 callbackBySurplus==================>,notifyResult:{}",notifyResult);

            String outTradeNo = notifyResult.getOutTradeNo();
            String transactionId = notifyResult.getTransactionId();
            List<SysBizRechargeUser> sysBizRechargeUsers = sysBizRechargeUserService.list(new LambdaQueryWrapper<SysBizRechargeUser>()
                    .eq(SysBizRechargeUser::getPaymentNo, outTradeNo));
            SysBizRechargeUser sysBizRechargeUser = null;
            if (!org.springframework.util.CollectionUtils.isEmpty(sysBizRechargeUsers)) {
                sysBizRechargeUser = sysBizRechargeUsers.get(0);
            }
            if (sysBizRechargeUser == null) {
                log.info("{}:订单为空", outTradeNo);
                return WxPayNotifyResponse.fail("失败");
            }
            if (SystemConst.PAY_SUCCESS.equals(notifyResult.getResultCode())) {
                Date nowDate = DateUtils.getNowDate();
                sysBizRechargeUser.setUpdateTime(nowDate);
                sysBizRechargeUser.setPayTime(nowDate);
                sysBizRechargeUser.setPaymentStatus(1);
                sysBizRechargeUser.setStatus(40);
                sysBizRechargeUser.setAuditStatus(1);
                sysBizRechargeUser.setTransactionId(transactionId);
                Integer giveType = sysBizRechargeUser.getGiveType();

                // 修改用户充值金额
                SysBizUser sysBizUser = sysBizUserService.selectSysBizUserById(sysBizRechargeUser.getUserId());
//                if (giveType != null && giveType.equals(1)) {
//                    // 优惠券
//                    SysBizCoupon byId = sysBizCouponService.getById(sysBizRechargeUser.getCouponId());
//                    SysBizCouponReceive couponReceiveRecord = sysBizCouponGrantService.createCouponReceiveRecord(sysBizUser, byId, 2);
//
//                    sysBizRechargeUser.setCouponReceiveId(couponReceiveRecord.getId());
//                }
                BigDecimal rechargeBalanceAfter = sysBizRechargeUser.getRechargeBalanceAfter();
                //sysBizUser.setSurplus(rechargeBalanceAfter);

                // 重新计算余额
                BigDecimal rechargeBalance = sysBizUser.getSurplus().add(sysBizRechargeUser.getRechargePrice());//.add(sysBizRechargeUser.getGivePrice())

                if (rechargeBalanceAfter.equals(rechargeBalance)) {
                    sysBizUser.setSurplus(rechargeBalance);
                    sysBizRechargeUser.setRechargeBalanceAfter(rechargeBalance);
                }else {
                    log.error("充值后的金额和充值记录数据不一致,rechargeBalanceAfter:{},rechargeBalanceAfter:{}",rechargeBalanceAfter,rechargeBalanceAfter);
                    return WxPayNotifyResponse.fail("失败");
                }

                sysBizRechargeUserService.updateById(sysBizRechargeUser);

                sysBizUserService.updateById(sysBizUser);

                // 新增充值记录
                sysBizUserSurplusDetailsService.save(SysBizUserSurplusDetails.builder()
                        .type(0)
                        .userId(sysBizUser.getId())
                        .tenantId(sysBizUser.getTenantId())
                        .rechargePrice(sysBizRechargeUser.getRechargePrice())
                        .price(sysBizRechargeUser.getRechargePrice()
                        .add(sysBizRechargeUser.getGivePrice()))
                        .orderId(sysBizRechargeUser.getOrderId())
                        .createTime(nowDate)
                        .createBy(sysBizUser.getNickName())
                        .build());
            }
            return WxPayNotifyResponse.success("成功");
        } catch (Exception e) {
            log.error("支付回调异常, error => ", e);
            return WxPayNotifyResponse.fail("失败");
        }
    }

    // 退款回调
    @PostMapping("/refundCallback")
    public String refundCallback(@RequestBody String xmlData) {
        try {
            log.info("================== refundCallback：{}",xmlData);

            WxPayOrderNotifyResult notifyResultXml = WxPayOrderNotifyResult.fromXML(xmlData);
            String transactionId1 = notifyResultXml.getTransactionId();
            SysBizOrder bizOrder = sysBizOrderService.getOne(new LambdaQueryWrapper<SysBizOrder>().eq(SysBizOrder::getTransactionId, transactionId1));
            if(bizOrder == null){
                return WxPayNotifyResponse.fail("未查询到订单站点配置信息");
            }

            SysBizTenant bizTenant = sysBizTenantService.getById(bizOrder.getTenantId());
            if(bizTenant == null){
                return WxPayNotifyResponse.fail("未查询到支付配置信息");
            }

            WxPayConfig payConfig = new WxPayConfig();
            payConfig.setAppId(StringUtils.trimToNull(appId));
            payConfig.setMchId(StringUtils.trimToNull(bizTenant.getWxMchId()));
            payConfig.setMchKey(StringUtils.trimToNull(bizTenant.getWxMchKey()));
//        payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
//        payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
            payConfig.setKeyPath(StringUtils.trimToNull(server+bizTenant.getWxKeyPath()));

            // 可以指定是否使用沙箱环境
            payConfig.setUseSandboxEnv(false);

            WxPayService wxPayService = new WxPayServiceImpl();
            wxPayService.setConfig(payConfig);

            final WxPayRefundNotifyResult notifyResult = wxPayService.parseRefundNotifyResult(xmlData);
            String outTradeNo = notifyResult.getResultCode();
            WxPayRefundNotifyResult.ReqInfo reqInfo = notifyResult.getReqInfo();
            log.info(JSONObject.toJSONString(reqInfo));
            String refund_status = reqInfo.getRefundStatus();// 退款状态
            String outRefundNo = reqInfo.getOutRefundNo();
            String transactionId = reqInfo.getTransactionId();
            log.info("================== refundCallback notifyResult：{}",notifyResult);
            int refundStatus = 0;
            if (SystemConst.PAY_SUCCESS.equals(notifyResult.getReturnCode())) {
                refundStatus = 1;
                log.info(transactionId + "退款成功");
                log.info("==================> notifyResult.getReturnCode()：{}",notifyResult.getReturnCode());
            } else {
                refundStatus = 2;
            }
//            SysBizOrderService sysBizOrderService = orderServiceService.selectSysBizOrderServiceByRefundNo(outRefundNo);
//            if (sysBizOrderService != null) {
//                sysBizOrderService.setRefundTime(new Date());
//                sysBizOrderService.setRefundStatus((long) refundStatus);
//                sysBizOrderService.setRemark(transactionId);
//            }
//            orderServiceService.updateSysBizOrderService(sysBizOrderService);
            return WxPayNotifyResponse.success("成功");
        } catch (Exception e) {
            log.error("微信小程序支付回调异常, error => ", e);
            return WxPayNotifyResponse.fail("失败");
        }
    }

}
